﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Company.Core.Helpers
{
    public static class IntOfBitHelper
    {
        /// <summary>
        /// 根据Int类型的值，返回用1或0(对应True或Flase)填充的数组
        /// <remarks>从右侧开始向左索引(0~31)</remarks>
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static IEnumerable<bool> GetBitList(int value)
        {
            var list = new List<bool>(32);
            for (var i = 0; i <= 31; i++)
            {
                var val = 1 << i;
                list.Add((value & val) == val);
            }
            return list;
        }

        /// <summary>
        /// 返回Int数据中某一位是否为1
        /// </summary>
        /// <param name="value"></param>
        /// <param name="index">32位数据的从右向左的偏移位索引(0~31)</param>
        /// <returns>true表示该位为1，false表示该位为0</returns>
        public static bool GetBitValue(int value, ushort index)
        {
            if (index > 31) throw new ArgumentOutOfRangeException("index"); //索引出错
            var val = 1 << index;
            return (value & val) == val;
        }

        /// <summary>
        /// 设定Int数据中某一位的值
        /// </summary>
        /// <param name="value">位设定前的值</param>
        /// <param name="index">32位数据的从右向左的偏移位索引(0~31)</param>
        /// <param name="bitValue">true设该位为1,false设为0</param>
        /// <returns>返回位设定后的值</returns>
        public static int SetBitValue(int value, ushort index, bool bitValue)
        {
            if (index > 31) throw new ArgumentOutOfRangeException("index"); //索引出错
            var val = 1 << index;
            return bitValue ? (value | val) : (value & ~val);
        }
/********************************************以下适用类型Int16\Int32\Int64******************************************/
        /// <summary>
        /// Int16\Int32\Int64类型
        /// </summary>
        /// <returns>true 1\false 0的集合</returns>
        public static IEnumerable<bool> GetIntOfBitList<T>(T intVal)
        {
            Type intType = intVal.GetType();
            byte bitlength = 0;
            if (intType == typeof(Int32))
                bitlength = 32;
            else if (intType == typeof(Int16))
                bitlength = 16;
            else if (intType == typeof(Int64))
                bitlength = 64;
            else
                throw new ArgumentException("必须是整型");

            object intOject = (object)intVal;
            var resultList = new List<bool>(bitlength);
            for (var i = 0; i < bitlength; i++)
            {
                var temoIntBit = 1 << i;
                if (intType == typeof(Int32))
                    resultList.Add((((Int32)intOject) & temoIntBit) == temoIntBit);
                if (intType == typeof(Int16))
                    resultList.Add((((Int16)intOject) & temoIntBit) == temoIntBit);
                if (intType == typeof(Int64))
                    resultList.Add((((Int64)intOject) & temoIntBit) == temoIntBit);
            }
            return resultList;
        }
        /// <summary>
        /// 获取T整型中某一位的值
        /// </summary>
        /// <typeparam name="T">泛型类型包括int\short\long</typeparam>
        /// <param name="intVal">int\short\long</param>
        /// <param name="index">从右到左0-T的总位数</param>
        /// <returns>true:1\false:0</returns>
        public static bool GetBitValue<T>(T intVal, byte index)
        {
            Type intType = intVal.GetType();
            byte bitlength = 0;
            if (intType == typeof(Int32))
                bitlength = 32; // bit位0..31
            else if (intType == typeof(Int16))
                bitlength = 16; // bit位0..15
            else if (intType == typeof(Int64))
                bitlength = 64; // bit位0..63
            else
                throw new ArgumentException("必须是整型");

            if (index > bitlength - 1 || index < 0)
                throw new ArgumentOutOfRangeException("index");

            object intOject = (object)intVal;
            var tempBit = 1 << index;

            if (intType == typeof(Int32))
                return (((int)intOject) & tempBit) == tempBit;
            else if (intType == typeof(Int16))
                return (((Int16)intOject) & tempBit) == tempBit;
            else
                return (((Int64)intOject) & tempBit) == tempBit;
        }
        /// <summary>
        /// 设置整型数据中某一位的值
        /// </summary>
        /// <typeparam name="T">int\short\long</typeparam>
        /// <param name="intVal">设置前的值</param>
        /// <param name="index">从右到左0-T的总位数</param>
        /// <param name="bitValue">需要设置的值 true:1\false:0</param>
        /// <returns>设置位值后新的整型</returns>
        public static T SetBitValue<T>(T intVal, byte index, bool bitValue)
        {
            Type intType = intVal.GetType();
            byte bitlength = 0;
            if (intType == typeof(Int32))
                bitlength = 32;
            else if (intType == typeof(Int16))
                bitlength = 16;
            else if (intType == typeof(Int64))
                bitlength = 64;
            else
                throw new ArgumentException("必须是整型");
            //不能去设置最高位
            if (index >= bitlength - 1 || index < 1)
                throw new ArgumentOutOfRangeException("index");

            object intOject = (object)intVal;
            var tempBit = 1 << index;

            if (intType == typeof(Int32))
            {
                int tempInt = (int)intOject;
                return (T)((bitValue ? (tempInt | tempBit) : (tempInt & ~tempBit)) as Object);
            }
            else if (intType == typeof(Int16))
            {
                Int16 tempInt = (Int16)intOject;
                return (T)((bitValue ? (tempInt | (Int16)tempBit) : (tempInt & ~tempBit)) as Object);
            }
            else
            {
                Int64 tempInt = (Int64)intOject;
                return (T)((bitValue ? (tempInt | (Int64)tempBit) : (tempInt & ~tempBit)) as Object);
            }
        }

    }
}
